/*
 * CoreVisualizer.java
 *
 * Created on October 18, 2006, 5:49 PM
 *
 * The Core Visualizer displays the contents of the JVM core registers in real-time.
 */

package emr.jvm.visualization;

import emr.jvm.*;
import emr.jvm.memory.MemoryController;
import emr.jvm.process.*;

import java.util.*;
import emr.jvm.memory.ram.*;
import javax.swing.SwingUtilities;


/**
 *
 * @author  Ross
 */
public class CoreVisualizer extends javax.swing.JFrame {
    
    private static final int initialDelay = 100;
    
    /** Reference to the core visualizer object */
    private static CoreVisualizer coreVisualizer = null;
    
    /** Creates new form CoreVisualizer */
    public CoreVisualizer() {
        
        initComponents();

        setTitle("Core Visualizer");
        setVisible(true);
        
        // set initial delay
        delaySlider.setValue(initialDelay);
        delayField.setText(Integer.toString(initialDelay));
        emr.jvm.process.ProcessManager.delayFactor = initialDelay;

        // set itself
        coreVisualizer = this;
    }
    
    
    /** Sets the instruction per second field to the value f */
    public static void setIPSField(final double ips)
    {
        if( coreVisualizer != null )
        {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    coreVisualizer.ipsField.setText(Double.toString(ips));
                }
            });
        }
    }
    
    
    /*
    
    private String visualizeQueue(Queue queue_)
    {
        String text = new String("");
        Iterator<Integer> iter = queue_.iterator();
             
        while(iter.hasNext())
        {
           
            int threadRef = iter.next();
            text = text.concat("Thread <" + Instance.getField(threadRef, ThreadInstance.getIdIndex(threadRef)) + 
                               "> p <" + Instance.getField(threadRef, ThreadInstance.getPriorityIndex(threadRef)) + 
                               "> d <" + Instance.getField(threadRef, ThreadInstance.getDelayIndex(threadRef)) + ">\n");
            
        }
        return text;
    }
    */
    
    /**
     *  Update the Eligible and Wait queues.  This method is run in the context of a JVMProcess
     */
    public void paintQueues()
    {
        paintQueue(JVMRuntime.eligiblehead, eligibleArea);
        paintQueue(JVMRuntime.waitinghead, waitArea);
    }
    
    /**
     *  Paints a particular queue by traversing the elements.  Do not paint a queue unless
     *  the objects in it are fully constructed and initialized!
     */
    public void paintQueue(int head_, final javax.swing.JTextArea textArea_)
    {
        //System.err.println("painting queue " + head_);
        if( head_ == JVMRuntime.nullregister )
            return;
        
        String text = new String("");

        int current = head_;
        
        while( current != JVMRuntime.nullregister )
        {
            
            // get values from current thread
            int id = MemoryController.readWord( current + ObjectBase.size + ObjectThread.IdOffset );
            int priority = MemoryController.readWord( current + ObjectBase.size + ObjectThread.PriorityOffset );
            int waketime = MemoryController.readWord( current + ObjectBase.size + ObjectThread.DelayOffset );
            
            // print values
            text = text.concat("<" + id + "> <" + priority + "> <" + Integer.toHexString(waketime) + ">\n");
                    
            current = MemoryController.readWord( current + ObjectBase.size + ObjectThread.NextOffset );
            
            //System.err.println("text: " + text);
        }

        // Everything above must occur concurrently with the invocation of this method (as part of the checkstatus
        // mechanism that each JVMProcess uses to update the visualization system).  However the update of the
        // GUI must occur synchronously on the swing event dispatch thread.
        final String textCopy = new String(text);
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                textArea_.setText(textCopy);
            }
        });
        
    }
    
    /**
     *  Static accessor method
     */
    public static void repaintQueues()
    {
        coreVisualizer.paintQueues();
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        delaySlider = new javax.swing.JSlider();
        delayField = new javax.swing.JTextField();
        delayLabel = new javax.swing.JLabel();
        startButton = new javax.swing.JButton();
        stepButton = new javax.swing.JButton();
        registerPanel = new javax.swing.JPanel();
        jScrollPane3 = new javax.swing.JScrollPane();
        registerArea = new javax.swing.JTextArea();
        ipsLabel = new javax.swing.JLabel();
        ipsField = new javax.swing.JTextField();
        debugButton = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        eligibleArea = new javax.swing.JTextArea();
        jScrollPane2 = new javax.swing.JScrollPane();
        waitArea = new javax.swing.JTextArea();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        instructionStep = new javax.swing.JButton();
        displayButton = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setName("Core Visualizer"); // NOI18N

        delaySlider.setMaximum(250);
        delaySlider.setMinorTickSpacing(10);
        delaySlider.setPaintTicks(true);
        delaySlider.setSnapToTicks(true);
        delaySlider.setValue(100);
        delaySlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                sliderHandler(evt);
            }
        });

        delayField.setEditable(false);

        delayLabel.setText("Delay");

        startButton.setText("Start");
        startButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                startButtonHandler(evt);
            }
        });

        stepButton.setText("Step");
        stepButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stepButtonActionPerformed(evt);
            }
        });

        registerPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Registers"));

        registerArea.setColumns(20);
        registerArea.setEditable(false);
        registerArea.setFont(new java.awt.Font("Monospaced", 0, 12));
        registerArea.setRows(5);
        jScrollPane3.setViewportView(registerArea);

        org.jdesktop.layout.GroupLayout registerPanelLayout = new org.jdesktop.layout.GroupLayout(registerPanel);
        registerPanel.setLayout(registerPanelLayout);
        registerPanelLayout.setHorizontalGroup(
            registerPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jScrollPane3, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 288, Short.MAX_VALUE)
        );
        registerPanelLayout.setVerticalGroup(
            registerPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jScrollPane3, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 458, Short.MAX_VALUE)
        );

        ipsLabel.setText("IPS");

        ipsField.setEditable(false);
        ipsField.setText("0");

        debugButton.setText("Debug Off");
        debugButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                debugButtonHandler(evt);
            }
        });

        eligibleArea.setColumns(20);
        eligibleArea.setRows(5);
        jScrollPane1.setViewportView(eligibleArea);

        waitArea.setColumns(20);
        waitArea.setRows(5);
        jScrollPane2.setViewportView(waitArea);

        jLabel1.setText("WaitQueue");

        jLabel2.setText("EligibleQueue");

        instructionStep.setText("Instruction Step");
        instructionStep.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                instructionStepHandler(evt);
            }
        });

        displayButton.setText("Display On/Off");
        displayButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                displayButtonHandler(evt);
            }
        });

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 218, Short.MAX_VALUE)
                    .add(layout.createSequentialGroup()
                        .add(startButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 66, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(stepButton))
                    .add(delaySlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 116, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(jLabel1)
                    .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 218, Short.MAX_VALUE)
                    .add(instructionStep)
                    .add(displayButton)
                    .add(jLabel2)
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, layout.createSequentialGroup()
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                    .add(delayLabel)
                                    .add(ipsLabel))
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                    .add(ipsField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 78, Short.MAX_VALUE)
                                    .add(delayField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 78, Short.MAX_VALUE)))
                            .add(debugButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 109, Short.MAX_VALUE))
                        .add(109, 109, 109)))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(registerPanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(startButton)
                            .add(stepButton))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(delaySlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .add(11, 11, 11)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(delayLabel)
                            .add(delayField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                        .add(18, 18, 18)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(ipsLabel)
                            .add(ipsField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(debugButton)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(layout.createSequentialGroup()
                                .add(29, 29, 29)
                                .add(displayButton))
                            .add(instructionStep))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jLabel2)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jLabel1)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 122, Short.MAX_VALUE))
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, registerPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .add(14, 14, 14))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void displayButtonHandler(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_displayButtonHandler
// TODO add your handling code here:
        JVMProcess.dumpRegisters = !JVMProcess.dumpRegisters;
    }//GEN-LAST:event_displayButtonHandler

    private void instructionStepHandler(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_instructionStepHandler
// TODO add your handling code here:
        JVMProcess.instructionStep = !JVMProcess.instructionStep;
    }//GEN-LAST:event_instructionStepHandler

    boolean debugToggle = true;
    
    private void debugButtonHandler(java.awt.event.ActionEvent evt)//GEN-FIRST:event_debugButtonHandler
    {//GEN-HEADEREND:event_debugButtonHandler
// TODO add your handling code here:
        // when clicked tooggle name: "Debug on"/"Debug off"
        
        // We must modify several components that actively display output during JVM operation:
        //   1. CoreVisualizer
        //   2. NVM Visualizer
        //   3. RAM Visualizer
        //   4. Debug output from processes.
        //   5. Bypass the sleep call in checkStatus()
        if( debugToggle )
        {
        
            MemoryVisualizer.showOutput = false;
            JVMProcess.processDebug = false;
            ProcessManager.debug = false;
            Debug.consoleLoggingEnabled = false;
            Debug.fileLoggingEnabled = false;
            debugButton.setText("Debug Off");
        }
        else
        {
            MemoryVisualizer.showOutput = true;
            JVMProcess.processDebug = true;
            ProcessManager.debug = true;
            Debug.consoleLoggingEnabled = true;
            debugButton.setText("Debug On");
            
        }
        
        
        debugToggle = !debugToggle;
        
    }//GEN-LAST:event_debugButtonHandler

    private void startButtonHandler(java.awt.event.ActionEvent evt)//GEN-FIRST:event_startButtonHandler
    {//GEN-HEADEREND:event_startButtonHandler
// TODO add your handling code here:
        ProcessManager.continueRun();
    }//GEN-LAST:event_startButtonHandler

    private void sliderHandler(javax.swing.event.ChangeEvent evt)//GEN-FIRST:event_sliderHandler
    {//GEN-HEADEREND:event_sliderHandler
// TODO add your handling code here:
        int delay = delaySlider.getValue();
        emr.jvm.process.ProcessManager.delayFactor = delay;
        delayField.setText( Integer.toString(delay));
    }//GEN-LAST:event_sliderHandler

    private void stepButtonActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_stepButtonActionPerformed
    {//GEN-HEADEREND:event_stepButtonActionPerformed
// TODO add your handling code here:
        ProcessManager.step();
    }//GEN-LAST:event_stepButtonActionPerformed
    
    public javax.swing.JTextArea getRegisterArea()
    {
        return registerArea;
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new CoreVisualizer().setVisible(true);
            }
        });
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton debugButton;
    private javax.swing.JTextField delayField;
    private javax.swing.JLabel delayLabel;
    private javax.swing.JSlider delaySlider;
    private javax.swing.JButton displayButton;
    private javax.swing.JTextArea eligibleArea;
    private javax.swing.JButton instructionStep;
    private javax.swing.JTextField ipsField;
    private javax.swing.JLabel ipsLabel;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JTextArea registerArea;
    private javax.swing.JPanel registerPanel;
    private javax.swing.JButton startButton;
    private javax.swing.JButton stepButton;
    private javax.swing.JTextArea waitArea;
    // End of variables declaration//GEN-END:variables
    
}
